[JavaScript] Compose 和 Pipe

Compose

Compose把多個函式組合成一個函式,關係式如下。

1
F(x) = f(g(x))

程式範例

1
2
3
4
5
6
7
8
9
10
11
var f = function(x){
return x + 1 ;
}
var g = function(x){
return x * 2 ;
}
f(g(1)); // 3
var F = compose(f,g);
F(1); // 3

實作

首先回傳一個函式,並利用閉包將傳入的函式紀錄起來。

1
2
3
4
5
6
var compose = function(){
var fns = arguments ;
return function(){
}
}

這個回傳的函式要依次執行函式參數,注意要從最後一個開始執行。

這裡使用 call 而不直接呼叫是為了以防函式使用到 this 的情形。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var compose = function(){
var fns = arguments ;
return function(result){
for ( var i = fns.length - 1 ; i >= 0 ; i -- ){
result = fns[i].call(this,result) ;
}
return result ;
}
}
var f = function(x){
return x + 1 ;
}
var g = function(x){
return x * 2 ;
}
f(g(1)); // 3
var F = compose(f,g);
F(1); // 3

可以使用reduce ,記得是從最後一個開始執行所以要使用 reduceRight

由於 reduce 用於陣列而 arguments 只是類陣列,所以先將 arguments 先轉為陣列。

1
2
3
4
5
6
7
8
9
function compose() {
var fns = Array.prototype.slice.call(arguments,0);
return function (arg) {
var result = fns.reduceRight(function(result , fn) {
return fn.call(this,result);
},arg);
return result;
};
};

Pipe

Pipe 其實和 Compose 很像,只是函式執行順序不一樣而已,因此改變程式順序即可。

1
2
3
4
5
6
7
8
9
function pipe() {
var fns = Array.prototype.slice.call(arguments,0);
return function (arg) {
var result = fns.reduce(function(result , fn) {
return fn.call(this,result);
},arg);
return result;
};
};

參考

Composing Functions in JavaScript